package com.bandaotixi.cashier.api.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.bandaotixi.cashier.api.common.constant.SystemConstants;
import com.bandaotixi.cashier.api.common.model.KeyValue;
import com.bandaotixi.cashier.api.common.model.Option;
import com.bandaotixi.cashier.api.common.result.PageResult;
import com.bandaotixi.cashier.api.common.result.Result;
import com.bandaotixi.cashier.api.core.mybatis.SqlUtil;
import com.bandaotixi.cashier.api.system.model.entity.Role;
import com.bandaotixi.cashier.api.system.model.query.RolePageQuery;
import com.bandaotixi.cashier.api.system.service.RoleService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 角色控制层
 */
@RestController
@RequestMapping("/roles")
@RequiredArgsConstructor
public class RoleController {

    private final RoleService roleService;

    @GetMapping("/page")
    public PageResult<Role> getRolePage(RolePageQuery queryParams) {
        Page<Role> result = roleService.lambdaQuery()
                .like(StringUtils.hasLength(queryParams.getKeywords()), Role::getName, queryParams.getKeywords())
                .ne(!StpUtil.hasRole(SystemConstants.ROOT_ROLE_CODE), Role::getCode, SystemConstants.ROOT_ROLE_CODE) // 非超级管理员不显示超级管理员角色
                .orderByAsc(Role::getSort).orderByDesc(Role::getCreateTime).orderByDesc(Role::getUpdateTime)
                .page(queryParams.page());
        return PageResult.success(result);
    }

    @GetMapping("/options")
    public Result<List<Option<Long>>> listRoleOptions() {
        List<Option<Long>> list = roleService.lambdaQuery()
                .ne(!StpUtil.hasRole(SystemConstants.ROOT_ROLE_CODE), Role::getCode, SystemConstants.ROOT_ROLE_CODE)
                .select(Role::getId, Role::getName)
                .orderByAsc(Role::getSort).list()
                .stream().map(role -> new Option<>(role.getId(), role.getName())).toList();
        return Result.success(list);
    }

    @PostMapping
    @SaCheckPermission("sys:role")
    public Result<?> addRole(@Valid @RequestBody Role roleForm) {
        boolean result = roleService.save(roleForm);
        return Result.judge(result);
    }

    @GetMapping("/{roleId}/form")
    public Result<Role> getRoleForm(@PathVariable Long roleId) {
        Role roleForm = roleService.getById(roleId);
        return Result.success(roleForm);
    }

    @PutMapping(value = "/{id}")
    @SaCheckPermission("sys:role")
    public Result<?> updateRole(@Valid @RequestBody Role roleForm) {
        boolean result = roleService.updateById(roleForm);
        return Result.judge(result);
    }

    @DeleteMapping("/{ids}")
    @SaCheckPermission("sys:role")
    public Result<Void> deleteRoles(@PathVariable String ids) {
        List<Long> idList = Arrays.stream(ids.split(",")).map(Long::parseLong).toList();
        roleService.removeByIds(idList);
        return Result.success();
    }

    @PutMapping(value = "/{roleId}/status")
    public Result<?> updateRoleStatus(@PathVariable Long roleId, @RequestParam Integer status) {
        Role role = roleService.getById(roleId);
        Assert.isTrue(role != null, "角色不存在");
        Assert.isTrue(!role.getCode().equals(SystemConstants.ROOT_ROLE_CODE), "超级管理员角色状态不允许修改");
        Assert.isTrue(status.equals(0) || status.equals(1), "角色状态不正确");
        boolean result = roleService.lambdaUpdate().eq(Role::getId, roleId).set(Role::getStatus, status).update();
        return Result.judge(result);
    }

    @GetMapping("/{roleId}/menuIds")
    public Result<List<Long>> getRoleMenuIds(@PathVariable Long roleId) {
        List<Long> menuIds = SqlUtil.relational("sys_role_menu", "menu_id", "role_id", Map.of("role_id", roleId))
                .stream().map(KeyValue::getKey).toList();
        return Result.success(menuIds);
    }

    @PutMapping("/{roleId}/menus")
    public Result<Void> assignMenusToRole(
            @PathVariable Long roleId,
            @RequestBody List<Long> menuIds
    ) {
        roleService.assignMenusToRole(roleId, menuIds);
        return Result.success();
    }
}
